<template>
  <client-only>
    <el-popover
      :placement="!!width ? 'bottom-start' : 'bottom'"
      :width="popoverWidth"
      trigger="click"
      transition="el-zoom-in-top"
      @show="showPopoverHandle"
      ref="popover">
      <el-tree :data="treeData"
               :node-key="nodeKey"
               :expand-on-click-node="false"
               :props="defaultProps"
               @node-click="treeClickHandle"
               ref="treeRef"
               class="tree"
               :style="{  '--minHeight': '200px', '--maxHeight': height + 'px' }"
      >
        <span slot-scope="{ node, data }" :class="{ 'disable-node': data[defaultProps.disabled] }"
              class="el-tree-node__label">{{ data[defaultProps.label] }}</span>
      </el-tree>
      <el-input :value="nodeValue" readonly ref="inputRef" slot="reference" :size="formSize" :placeholder="placeholder"
                :class="className">
      </el-input>
    </el-popover>
  </client-only>
</template>

<script>
  export default {
    name: "tree-select",
    props: {
      // 表单大小
      formSize: {
        type: String,
        default: 'small'
      },
      // 数据对象
      dataObj: {
        type: Object,
        default: () => {
          return {}
        }
      },
      // 展示的属性key
      propKey: {
        type: String,
        default: 'name'
      },
      // 树节点唯一标识
      nodeKey: {
        type: String,
        default: 'id'
      },
      // 树数据列表
      treeData: {
        type: Array,
        default: () => []
      },
      // 树属性配置对象
      defaultProps: {
        type: Object,
        default: () => {
          return {
            children: 'children',
            label: 'name',
            disabled: 'disabled'
          }
        }
      },
      // el-popover宽度值
      width: {
        type: Number
      },
      // el-tree最大高度值
      height: {
        type: Number,
        default: 300
      },
      // 自定义class
      className: {
        type: String,
        default: ''
      },
      // 输入款placeholder
      placeholder: {
        type: String,
        default: ''
      }
    },
    data() {
      return {
        // popover宽度
        popoverWidth: this.width,
        // 树结构选中值
        // nodeValue: ''
      }
    },
    computed: {
      nodeValue() {
        if (this.dataObj[this.propKey]) {
          /*
            回显结构树选中值
           */
          let queue = [...this.treeData];
          while (queue.length > 0) {
            let node = queue.shift();
            if (node[this.nodeKey] === this.dataObj[this.propKey]) {
              // 回显名称
              return node[this.defaultProps.label];

            }
            if (node[this.defaultProps.children]) {
              queue.push(...node[this.defaultProps.children]);
            }
          }
        }
        return '';
      }
    },
    methods: {
      /**
       * 显示popover时回调方法
       */
      showPopoverHandle() {
        if (this.treeData.length === 1) {
          // 结构树顶级列表只有一个数据，则默认展开该节点
          let node = this.treeData[0];
          // 展开节点
          this.$refs.treeRef.store.nodesMap[node[this.nodeKey]].expanded = true;
        }
        if (!this.width) {
          /*
            计算Popover组件宽度
           */
          // 获取虚拟dom对象
          let inputRef = this.$refs.inputRef;
          // console.log('inputRef', inputRef);
          // 获取原生dom对象
          let inputRefEl = inputRef.$el;
          // console.log('inputRefEl', inputRefEl);
          // 获取子dom列表
          let children = inputRefEl.children;
          // console.log('children', children);
          if (children) {
            // 获取第一个子dom对象（input输入框dom元素）
            let firstChildren = children[0];
            // console.log('firstChildren', firstChildren);
            /*
              1、获取dom元素的实际宽度（width + 左右padding）
              2、减去24px以适配input输入框的宽度
             */
            this.popoverWidth = firstChildren.clientWidth;
            // console.log('width', this.popoverWidth);
          }
        }
      },
      /**
       * 树节点点击事件
       * @param data    树节点原始对象
       * @param node    树节点对象
       * @param nodeDom 节点组件对象
       */
      treeClickHandle(data, node, nodeDom) {
        if (!data[this.defaultProps.disabled]) {
          const value = data[this.propKey];
          const isUpdate = value !== this.dataObj[this.propKey];
          // 向上传递事件
          this.$emit('node-click', data, value, isUpdate);

          // 关闭popover
          document.body.click();
        }
      },
    },
  }
</script>

<style scoped>
  .tree {
    overflow-y: auto;
    --minHeight: 100px;
    --maxHeight: 300px;
    min-height: var(--minHeight);
    max-height: var(--maxHeight);
  }
  .tree >>> > .el-tree-node {
    display: inline-block;
    min-width: 100%;
  }
  .tree >>> .disable-node {
    color: #C0C4CC;
    cursor: not-allowed;
  }
</style>
